{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Configure chain internals at runtime\n",
    "\n",
    "Oftentimes you may want to experiment with, or even expose to the end user, multiple different ways of doing things. In order to make this experience as easy as possible, we have defined two methods.<br>\n",
    "通常，您可能想要尝试，甚至向最终用户展示多种不同的做事方式。为了使这种体验尽可能简单，我们定义了两种方法。\n",
    "\n",
    "1. First, a configurable_fields method. This lets you configure particular fields of a runnable.<br>\n",
    "首先，一种 configurable_fields 方法。这允许您配置可运行对象的特定字段。\n",
    "\n",
    "2. Second, a configurable_alternatives method. With this method, you can list out alternatives for any particular runnable that can be set during runtime.<br>\n",
    "第二，方法 configurable_alternatives 。使用此方法，您可以列出可在运行时设置的任何特定可运行对象的备选方案。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Configuration Fields"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='57', response_metadata={'token_usage': {'completion_tokens': 1, 'prompt_tokens': 11, 'total_tokens': 12}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-b93ff62b-c42d-4703-b3fd-e4eea48fdcdd-0', usage_metadata={'input_tokens': 11, 'output_tokens': 1, 'total_tokens': 12})"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain_core.prompts import PromptTemplate\n",
    "from langchain_core.runnables import ConfigurableField\n",
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "model = ChatOpenAI(temperature=0).configurable_fields(\n",
    "    temperature=ConfigurableField(\n",
    "        id=\"llm_temperature\",\n",
    "        name=\"LLM Temperature\",\n",
    "        description=\"The temperature of the LLM\",\n",
    "    )\n",
    ")\n",
    "model.invoke(\"pick a random number\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='18', response_metadata={'token_usage': {'completion_tokens': 1, 'prompt_tokens': 11, 'total_tokens': 12}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-b755ec32-808b-451d-857b-e296e815a762-0', usage_metadata={'input_tokens': 11, 'output_tokens': 1, 'total_tokens': 12})"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.with_config(configurable={\"llm_temperature\": 0.9}).invoke(\"pick a random number\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='75', response_metadata={'token_usage': {'completion_tokens': 1, 'prompt_tokens': 14, 'total_tokens': 15}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-056ffa73-78a2-4386-bb74-8b62d4a1e901-0', usage_metadata={'input_tokens': 14, 'output_tokens': 1, 'total_tokens': 15})"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "prompt = PromptTemplate.from_template(\"Pick a random number above {x}\")\n",
    "chain = prompt | model\n",
    "chain.with_config(configurable={\"llm_temperature\": 0.6}).invoke({\"x\": 0})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.runnables.hub import HubRunnable\n",
    "\n",
    "prompt = HubRunnable(\"rlm/rag-prompt\").configurable_fields(\n",
    "    owner_repo_commit=ConfigurableField(\n",
    "        id=\"hub_commit\",\n",
    "        name=\"Hub Commit\",\n",
    "        description=\"The Hub commit to pull from\",\n",
    "    )\n",
    ")\n",
    "\n",
    "prompt.with_config(configurable={\"hub_commit\": \"rlm/rag-prompt-llama\"}).invoke(\n",
    "    {\"question\": \"foo\", \"context\": \"bar\"}\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Configurable Alternatives"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_community.chat_models import ChatAnthropic\n",
    "from langchain_core.prompts import PromptTemplate\n",
    "from langchain_core.runnables import ConfigurableField\n",
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "llm = ChatAnthropic(temperature=0).configurable_alternatives(\n",
    "    # This gives this field an id\n",
    "    # When configuring the end runnable, we can then use this id to configure this field\n",
    "    ConfigurableField(id=\"llm\"),\n",
    "    # This sets a default_key.\n",
    "    # If we specify this key, the default LLM (ChatAnthropic initialized above) will be used\n",
    "    default_key=\"anthropic\",\n",
    "    # This adds a new option, with name `openai` that is equal to `ChatOpenAI()`\n",
    "    openai=ChatOpenAI(),\n",
    "    # This adds a new option, with name `gpt4` that is equal to `ChatOpenAI(model=\"gpt-4\")`\n",
    "    gpt4=ChatOpenAI(model=\"gpt-4\"),\n",
    "    # You can add more configuration options here\n",
    ")\n",
    "prompt = PromptTemplate.from_template(\"Tell me a joke about {topic}\")\n",
    "chain = prompt | llm\n",
    "# By default it will call Anthropic\n",
    "chain.invoke({\"topic\": \"bears\"})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-07-23T04:04:50.291580Z",
     "start_time": "2024-07-23T04:04:47.503516Z"
    }
   },
   "outputs": [],
   "source": [
    "from langchain_anthropic import ChatAnthropic\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "from langchain_core.runnables import RunnablePassthrough\n",
    "from langchain_core.output_parsers import StrOutputParser\n",
    "import os\n",
    "\n",
    "# os.environ[\"ANTHROPIC_API_URL\"] = \"https://api.openai-hk.com\"\n",
    "# os.environ[\"ANTHROPIC_API_KEY\"] = \"hk-a2rmcr1000012639ed07fc890784046f38ab1c60f3d07e19\"\n",
    "\n",
    "anthropic = ChatAnthropic(model=\"claude-2\")\n",
    "prompt = ChatPromptTemplate.from_template(\n",
    "    \"Tell me a short joke about {topic}\"\n",
    ")\n",
    "output_parser = StrOutputParser()\n",
    "anthropic_chain = (\n",
    "    {\"topic\": RunnablePassthrough()} \n",
    "    | prompt \n",
    "    | anthropic\n",
    "    | output_parser\n",
    ")\n",
    "\n",
    "anthropic_chain.invoke(\"ice cream\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "langchain0_1",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
